home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 307.adf / FileIO / BasicFileIO (.txt) < prev    next >
AmigaBASIC Source Code  |  1990-01-13  |  16KB  |  356 lines

  1.  'As you probably already know; AmigaBasic SUCKS! It can't handle structures.
  2.  'Yet another shoddy Microsoft product. Actually, this is about the fifth
  3.  'basic program I've ever written. The other four were done in a 15 week
  4.  'course some years back in college. I'm an assembly programmer, and usually
  5.  'I don't touch this crap, but someone had to write an example. The code is
  6.  'probably not too efficient, but it's the first basic program I've written
  7.  'in years, the first in AmigaBasic, and was done in about 2 hours (I had to
  8.  'read the AmigaBasic instruction book. Really.) I cannot begin to tell you
  9.  'how excruciating the AmigaBasic editor is to an assembly programmer.
  10.  
  11.  CLS
  12.  LOCATE 1,8
  13.  PRINT "Demo AmigaBasic program using the FileIO requester library."
  14.  LOCATE 2,11
  15.  PRINT "Literally hacked together by Jeff Glatt (dissidents)"
  16.  
  17.  DEFLNG a-Z  'IMPORTANT! All variables are longs (for the library calls)
  18.  
  19.  'requester.bmap and exec.bmap must be in the current directory
  20.  LIBRARY "requester.library"
  21.  LIBRARY "exec.library"
  22.  
  23.  DECLARE FUNCTION AllocMem() LIBRARY
  24.  
  25.  DECLARE FUNCTION DoFileIOWindow() LIBRARY  'These are in the FileIO lib.
  26.  DECLARE FUNCTION GetFullPathname() LIBRARY 'Other functions in the lib do
  27.  DECLARE FUNCTION GetFileIO() LIBRARY       'not return values, and so do not
  28.  DECLARE FUNCTION AutoFileMessage() LIBRARY 'need declaring
  29.  DECLARE FUNCTION AutoPrompt3() LIBRARY
  30.  DECLARE FUNCTION TypeFilename() LIBRARY
  31.  DECLARE FUNCTION UserEntry() LIBRARY
  32.  DECLARE FUNCTION PromptUserEntry() LIBRARY
  33.  DECLARE FUNCTION GetRawkey() LIBRARY
  34.  DECLARE FUNCTION DecodeRawkey() LIBRARY
  35.  
  36.  'First we must get a buffer for the pathname. The FileIO's DoFileIOWindow()
  37.  'will copy the complete pathname there. The complete path looks just like
  38.  'a CLI line:
  39.  
  40.  '  Diskname:TopDrawer/SubDrawer...etc...BottomDrawer/Filename
  41.  
  42.  'Of course, the user may only select a disk or drawer, but no filename, and
  43.  'so the final "/Filename" will not be there. Also, the Filename might not
  44.  'be in any drawers, and so it will appear directly after the diskname. If
  45.  'this format looks weird to you, you need to learn about the CLI.
  46.  'We'll get our buffer from Exec via AllocMem(). 
  47.   
  48.  MEMF.PUBLIC = 1 : MEMF.CLEAR = 65536 : BUFSIZE = 202
  49.  BufferPtr=AllocMem(BUFSIZE,MEMF.PUBLIC+MEMF.CLEAR) 'A buffer to copy the pathname to
  50.  IF BufferPtr = 0 THEN GOTO NoMem1 
  51.  
  52.  'Now we need to get a buffer if we want to allow the user to utilize the
  53.  'extention match feature.
  54.  BUFSIZE2 = 24
  55.  ExtPtr=AllocMem(BUFSIZE2,MEMF.PUBLIC+MEMF.CLEAR)
  56.  IF ExtPtr = 0 THEN GOTO NoMem2 
  57.  
  58.  FileIO=GetFileIO(0)  'Get the address of the FileIO structure
  59.                        'Actually you don't need to pass the 0, but AmigaBasic seems to want something...
  60.  
  61.  IF FileIO = 0 THEN GOTO CloseUp1 '0 means that you don't have a FileIO.
  62.  
  63.  'Set the FileIO's Buffer field to our allocated PathBuffer's address
  64.  POKEL FileIO+248,BufferPtr
  65.  
  66.  POKEL FileIO+222,ExtPtr 'Set the address of the extention string
  67.  
  68.  'Set the title that will displayed in the FileIO window. This can be changed
  69.  'for each call so that you might have the title read "Save File" during a
  70.  'save routine, for example.
  71.  
  72.  WindowTitle$ = "FileIO Basic Example"
  73.  POKEL FileIO+244,SADD(WindowTitle$)
  74.  
  75.  'Set the fore pen, back pen, and draw mode for title bar routines to some
  76.  'defaults. We always need to do this in case the requester is in use by
  77.  'another program and we get automatic title bar file entry. To demo this,
  78.  'run this program twice simultaneously with one of them having the file
  79.  'requester displayed. Note that the title bar entry appears in the 2nd
  80.  'window. This is because only 1 task can be displaying the FileIO requester
  81.  'at a time. Other simultaneous calls get redirected to the title bar entry.
  82.  
  83.  POKE  FileIO+261,1  'JAM2 DrawMode
  84.  POKE  FileIO+262,1  'PenA = Color1
  85.  POKE  FileIO+263,0  'PenB = Color0
  86.  DIM   Pathname$(202)
  87.  DIM   Filename$(30)
  88.  DIM   VolName$(30)
  89.  DIM   DrawerName$(132)
  90.   
  91. Again:
  92.  
  93.  'First I'll demo 2 things you can do with the Flags field of the FileIO. The
  94.  'FileIO is a structure, and our variable name FileIO is just the start (base)
  95.  'of that structure (block of memory). We can access any field of the FileIO
  96.  'by PEEKing and POKEing various fields. You should POKE a value into the
  97.  'FileIO, and retrieve a value by PEEKing. Some fields are larger than 1 byte
  98.  'and you must use PEEKW, PEEKL, POKEW, POKEL. You need to know how far away
  99.  'the field is from the base of the structure. The flags field is one byte
  100.  'away, so to access it we PEEK or POKE to FileIO+1. The previous initialization
  101.  'we did for the window title was at an offset of 244 from the base, and was
  102.  'a LONGWORD (4 bytes). That's why I added the L to POKE.
  103.  
  104.  'Since the user can always set these features up for himself via the 10
  105.  'functions keys (see the doc), normally you wouldn't bother with the Flags
  106.  'field unless you had something particular in mind...but for a demo...
  107.  
  108.  LOCATE 3,1
  109.  'See if the user wants only those filenames that end in a certain extention
  110.  'Actually, the user can change this string after the requester opens via F4
  111.  'so you should never assume that the returned filename will indeed end in
  112.  'this string. If the user changes it, he probably knows what he's doing. Ha, ha.
  113.  INPUT "Do you want only those filenames with a certain extention (y or n)";Ans$
  114.  IF Ans$ <> "y" THEN GOTO SkipExt
  115.  INPUT "Type the extention, 14 chars max (i.e., .device)";EXT$
  116.  extsize=LEN(EXT$)
  117.  IF extsize = 0  THEN GOTO SkipExt
  118.  IF extsize > 13 THEN GOTO SkipExt 'too long
  119. 'Enable the extention match feature of the FileIO
  120.   POKE  FileIO+1,4            'Turn on extention match feature only
  121.   POKEW FileIO+226,extsize    'Get the length of the string
  122.   'Copy the user string to the extention buffer
  123.   EXT$ = UCASE$(EXT$)  'must be upper case
  124.   FOR i = 0 TO 13
  125.     char$ = EXT$(i)
  126.     value = ASC(char$)
  127.     POKE(BufferPtr+i),value    
  128.   NEXT i 
  129.   POKE(BufferPtr+14),0
  130.   GOTO   DoIO
  131.   
  132. SkipExt:  'Otherwise, at least suppress the .info files
  133.   POKE  FileIO+1,128
  134.   
  135. DoIO:
  136.  Result=DoFileIOWindow(FileIO,0)  'do the FileIO selection on WB screen  
  137.  
  138.  IF Result <> -1 THEN GOTO CheckError    '-1 means the user selected CANCEL.
  139.  message$ = "User selected CANCEL."+CHR$(0)
  140.  CALL AutoMessageLen(SADD(message$),WINDOW(7),21) '21 is the number of chars in Message$ not counting the CHR$(0)
  141.  GOTO CloseUp2
  142.  
  143. CheckError:
  144.  '0 means the FileIO window couldn't open due (probably due to lack of mem).
  145.  'Too bad! You'll have to get the filename some other way. Maybe an INPUT statement?
  146.  IF Result <> 0 THEN GOTO GotPathname              
  147.  'Message number 0 in the FileIO lib says "Out of memory for this operation" 
  148.  Result=AutoFileMessage(0,WINDOW(7))
  149.  INPUT "Type path: ";Pathname$
  150.  CALL ParseString(FileIO,SADD(Pathname$))
  151.  GOTO CopyFN
  152.  
  153. GotPathname:       'We got a selection from the user!
  154.  'Now, our PathBuffer$ has the complete pathname. The FileIO's Filename
  155.  'buffer has just the Filename separated from the disk and drawer names
  156.  '(which are also separated into their own FileIO buffers). Let's copy out
  157.  'each of these buffers so that we can print the separate pieces, plus copy
  158.  'the complete path.
  159.  
  160.  Pathname$ = ""
  161.  FOR i = 0 TO 202
  162.     value = PEEK(BufferPtr+i)
  163.     IF value = 0 THEN GOTO CopyFN
  164.     char$ = CHR$(value)
  165.     Pathname$ = Pathname$+char$    
  166.  NEXT i 
  167.  
  168. CopyFN:
  169.   Filename$ = ""
  170.  'Copy out the Filename to Filename$.
  171.  FOR i = 0 TO 30
  172.     value = PEEK(FileIO+2+i)
  173.     IF value = 0 THEN GOTO CopyDrawer
  174.     char$ = CHR$(value)
  175.     Filename$ = Filename$+char$    
  176.  NEXT i
  177.  
  178. CopyDrawer: 'Copy out all the drawers 
  179.  DrawerName$ = ""
  180.  FOR i = 0 TO 132
  181.     value = PEEK(FileIO+32+i)
  182.     IF value = 0 THEN GOTO CopyVol
  183.     char$ = CHR$(value)
  184.     DrawerName$ = DrawerName$+char$    
  185.  NEXT i
  186.  
  187. CopyVol: 'Copy out the diskname 
  188.  VolName$ = ""
  189.  FOR i = 0 TO 30
  190.     value = PEEK(FileIO+164+i)
  191.     IF value = 0 THEN GOTO PrintPath
  192.     char$ = CHR$(value)
  193.     VolName$ = VolName$+char$    
  194.  NEXT i
  195.  
  196. PrintPath:   'Print out all the info available in the FileIO
  197.  LOCATE 7,1
  198.  
  199. noExt:
  200.  CALL AutoMessage(SADD(Pathname$),WINDOW(7)) 'display our complete path in a
  201.                                              'requester first
  202.  
  203.  PRINT
  204.  'Let's print out the disk, drawers, and filename.
  205.  PRINT "The Diskname is ",VolName$
  206.  PRINT "The Drawernames are ",DrawerName$
  207.  PRINT "The Filename is ",Filename$ 'Note that there is no Filename if the
  208.                                     'user selected only a disc or drawer.
  209.   
  210.  'Let's get the amount of free disk space on the disk that the user chose.
  211.  'This could be important if we were trying to save something to this disk
  212.  'and there wasn't enough room. Also, if the user typed in a disc or drawer
  213.  'that didn't exist or he refused to place that disc in the drive, the
  214.  'returned default disc is ":" which is the current directory.
  215.  PRINT "Free disk space: ",PEEKL(FileIO+236)," bytes."
  216.  
  217.  'Now if this is a loadable file, the FileIO has it's size. If it's only a
  218.  'disc name or dir, or the file doesn't exist, then the size = 0.
  219.  extsize=LEN(Filename$)  'Did the user finally select a file?
  220.  IF extsize = 0 THEN GOTO DiscOrDir         'Must be a disk or drawer only 
  221.  IF PEEKL(FileIO+240) = 0 THEN GOTO NoExist 'Aha! User typed in a Filename that doesn't yet exist
  222.  PRINT "Size of file:    ",PEEKL(FileIO+240)," bytes."
  223.  
  224.  ' Now, you might want to do a load or save routine using this user selected
  225.  ' pathname. You can check the FileIO's FILE.BYTESIZE (FileIO+240) field to see if the
  226.  ' user actually selected an existing file, or typed in a new, non-existant
  227.  ' name. For example, say that the user selected a directory but not a file
  228.  ' within the directory. The returned pathname might be
  229.  '            DF0:SomeDrawerName
  230.  ' In this case, the FILE.BYTESIZE field would be 0 and if you tried to "load"
  231.  ' the file, you would get a DOS error message. Likewise, if the user types
  232.  ' in a non-existant file name, this field is also 0, but you can open the
  233.  ' file for writing (save). If the user's selected pathname is the name of
  234.  ' an object file (not just a dir or disk), then this is the only time that
  235.  ' FILE.BYTESIZE will not be 0. In fact, it will be the size of the file. In
  236.  ' conclusion, if you were doing a load routine, you would do the following
  237.  ' steps at this point:
  238.  ' 1). Check if there is some name in the FileIO's Filename field. If not,
  239.  '     this means that the user selected a disk or drawer only. Abort the load.
  240.  ' 2). Check to see if the FILE.BYTESIZE field is 0. If it is 0, then the
  241.  '     user has typed in a file that doesn't exist (in whichever dir that he
  242.  '     finally chose). Display a message that says "File doesn't exist".
  243.  ' 3). If the FILE.BYTESIZE is not 0, then you can open the file for reading
  244.  '     and copy this many bytes into memory. Since AmigaBasic doesn't have a
  245.  '     facility for loading blocks of bytes, I recommend the DOS library.
  246.  '
  247.  '    LIBRARY "dos.library"
  248.  '    LIBRARY "intuition.library"   
  249.  '    DECLARE  FUNCTION  Open() LIBRARY
  250.  '    DECLARE  FUNCTION  Read() LIBRARY
  251.  '    DECLARE  FUNCTION  Write() LIBRARY 
  252.  
  253.  '    Filehandle=Open(BufferPtr,1005&)
  254.  '    IF Filehandle <> 0 THEN GOTO GotIt 
  255.  '        Message$ = "Cannot locate this file!"+CHR$(0) 'Oops Can't find it.
  256.  '        CALL AutoMessageLen(SADD(Message$),WINDOW(7),24&)
  257.  '        GOTO BadLoad
  258.  'GotIt:
  259.  '    CALL SetWaitPointer(WINDOW(7))
  260.  '    Bytes=PEEKL(FileIO+240)
  261.  '    DIM DataBuffer(Bytes)   'read the file into this 1-D array
  262.  '    Result=Read(Filehandle,VARPTR(DataBuffer(0)),Bytes)
  263.  '    CALL Close(Filehandle)
  264.  '    CALL ClearPointer(WINDOW(7))  'must have intuition open
  265.  '    IF Result = Bytes THEN GOTO GoodLoad 
  266.  '      boolean=AutoFileMessage(2&,WINDOW(7)) 'tell the user that an error occured
  267.  '      GOTO BadLoad
  268.  'GoodLoad:
  269.  
  270.  '    You can now "pull out" data from DataBuffer as you need it (like we
  271.  '    extracted data from FileIO except perhaps you might not want to
  272.  '    convert the value to ascii via CHR$).
  273.   
  274.  ' If you were doing a save routine to disk, you would do the following:
  275.  ' 1). Check if there is some name in the FileIO's Filename field. If not,
  276.  '     this means that the user selected a disk or drawer only. Abort the save.
  277.  ' 2). Check if FILE.BYTESIZE is not 0. If not 0, inform the user that this
  278.  '     file already exists and if you save using this name, you will write
  279.  '     over the other file. Ask the user if he wants to do the save anyway.
  280.  ' 3). If FILE.BYTESIZE is 0, this file doesn't already exist. Check that the
  281.  '     free disk space is greater than the number of bytes that we want to
  282.  '     save, or else we'll run out of room during the save.
  283.  '
  284.  '  Let's say that you stored the data in a big 1-D array called DataTank
  285.  '  and the number of bytes you want to save is 32.
  286.  '
  287.  '  Bytes=32&
  288.  '  Filehandle=Open(BufferPtr,1006&)
  289.  '  IF Filehandle <> 0 THEN GOTO CreateIt 
  290.  '        Message$ = "Cannot create the file!"+CHR$(0) 'Oops Can't save it.
  291.  '        CALL AutoMessageLen(SADD(Message$),WINDOW(7),23&)
  292.  '        GOTO BadSave
  293.  '  CALL SetWaitPointer(WINDOW(7))
  294.  '  Result=Write(Filehandle,VARPTR(DataTank(0)),Bytes)
  295.  '  CALL Close(Filehandle)
  296.  '  CALL ClearPointer(WINDOW(7)) 
  297.  '  IF Result = Bytes THEN GOTO GoodSave
  298.  '      boolean=AutoFileMessage(2&,WINDOW(7)) 'tell the user that an error occured
  299.  '      GOTO BadSave
  300.  'GoodSave:
  301.  
  302. Retry:
  303.  message$  = "This has been a test of the FileIO library." + CHR$(0)
  304.  Message2$ = "Do you want to retry?" + CHR$(0)
  305.  boolean=AutoPrompt3(SADD(message$),SADD(Message2$),0,WINDOW(7))
  306.  CLS
  307.  IF boolean = 1 THEN GOTO Again
  308.  
  309.  'Note how the lib automatically spaces these messages symmetrically
  310.  
  311.  message$ = "Example program and asm lib by Jeff Glatt" + CHR$(0)
  312.  Message2$ = "(dissidents)" + CHR$(0)
  313.  Message3$ = "Original FileIO by RJ Mical" + CHR$(0)
  314.  boolean=AutoPrompt3(SADD(message$),SADD(Message2$),SADD(Message3$),WINDOW(7))  
  315.  
  316. CloseUp2: 
  317.  
  318.  CALL ResetTitle(FileIO,WINDOW(7)) 'Maybe we changed it for the error msgs.
  319.  CALL ReleaseFileIO(FileIO)        'Free the FileIO structure
  320.   
  321. CloseUp1:
  322.  CALL  FreeMem(ExtPtr,BUFSIZE2)
  323.  
  324. NoMem2:
  325.  CALL  FreeMem(BufferPtr,BUFSIZE)
  326.  
  327. NoMem1: 
  328.  LIBRARY CLOSE
  329.  END
  330.  
  331.  ' For these 2 errors, let's see how the SetTitle function works. This will
  332.  ' display in the window's title bar string1 followed by string2, but unlike
  333.  ' a requester, returns control back to the program. When we finally call
  334.  ' ResetTitle, the original title is restored. We can call SetTitle without
  335.  ' needing a ResetTitle inbetween and vica versa. Notice how this message
  336.  ' appears in the window and requester title bars. Subsequent calls to these
  337.  ' error routines (answer "Yes" to the again requester and cause another
  338.  ' error) will change the title bar further. Yet, when we finally call
  339.  ' ResetTitle upon exit, the initial title is restored. As you can see, these
  340.  ' routines are good for posting error msgs that don't halt the program (like
  341.  ' requesters) but remain visible for as long as they are needed.
  342.  
  343. DiscOrDir:
  344.   message$ = "Dir only - "+CHR$(0)
  345.  'String2 will be our Pathname
  346.   CALL SetTitle(SADD(message$),SADD(Pathname$),FileIO,WINDOW(7))
  347.   GOTO Retry
  348.  
  349. NoExist:
  350.   message$ = "This file doesn't exist."+CHR$(0)
  351.   'Note how we indicate that we don't want String2. You must have string1
  352.   'though, even it were just a space.
  353.   CALL SetTitle(SADD(message$),0,FileIO,WINDOW(7))
  354.   GOTO Retry
  355.  
  356.